//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;

namespace Eas.WebCrawler.Common.Diagnostics {
    /// <summary>This class provides wrappers of incrementing numeric values for use in tracing.</summary>
    /// <remarks>The name for this class comes from the ticket dispensers at deli counters that also dispenser increasing numbers over and over.
    /// Just like at the deli counter, when this dispenser reaches it's maximum value, it flips back around to one.</remarks>
    public class DeliTicketDispenser {
        private long TicketValue=-1;
        /// <summary>The maximum value that a dispensed ticket can hold before the tickets wrap back around to 0;</summary>
        public const long MaximumValue = long.MaxValue - 10L;
        
        /// <summary>Get's the next value as a long.</summary>
        /// <returns>One greater then the previously dispensed value.</returns>
        /// <remarks>The first call to this fiuntion should return 0, and if the value ever get's larger than <see cref="MaximumValue"/> than <code>0</code> is returned again.</remarks>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
        public long GetNextAsLong() {
            long currentValue = TicketValue;
            long startValue;
            long desiredValue;
            do {
                startValue = currentValue;
                desiredValue = currentValue + 1;
                if (desiredValue > MaximumValue) {
                    desiredValue = 0;
                }
                currentValue = System.Threading.Interlocked.CompareExchange(ref TicketValue, desiredValue, startValue);
            } while (currentValue != startValue);
            return desiredValue;
        }

        /// <summary>Returns a reference type wrapper around the nex value to dispense.</summary>
        /// <returns>A thin reference type wrapper around the next dispensed value.</returns>
        /// <remarks>The first call to this fiuntion should return 0, and if the value ever get's larger than <see cref="MaximumValue"/> than <code>0</code> is returned again.</remarks>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
        public ReferenceTypeWrapper<long> GetNextAsWrapper() {
            return new ReferenceTypeWrapper<long>(GetNextAsLong());
        }
       
    }
}
